package cn.iocoder.yudao.module.call.framework.client.impl.dywl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.call.api.client.dto.*;
import cn.iocoder.yudao.module.call.framework.client.impl.AbstractCallClient;
import cn.iocoder.yudao.module.call.framework.client.property.CallProperties;
import cn.iocoder.yudao.module.call.enums.CallResultTypeEnum;
import cn.iocoder.yudao.module.call.utils.TimeUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 北京点易未来 双向回拨 sdk
 */
@Slf4j
public class DYWLClient extends AbstractCallClient {

    final static String url = "http://36.138.48.229:19501";

    final static String CALL_API = "/cbs/submit";
    final static String HANGUP_API = "/cbs/cancel";


    final static String ERROR_MSG = "未接通";

    final static Integer SERVICE_TYPE = 5;

    final static Integer INDUSTRY_TYPE = 1;

    @Override
    protected void doInit() {

    }

    public DYWLClient(CallProperties properties) {
        super(properties);
        // check config properties not null
        Assert.notNull(properties.getAppKey(), "AccessKey 不能为空");
        Assert.notNull(properties.getAppSecret(), "AppSecret 不能为空");
        Assert.notNull(properties.getNotifyUrl(), "话单推送地址不能为空");
    }

    @Override
    public CallRespDTO handleCall(CallReqDTO callReqDTO) {
        String timeStamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
        String password = DigestUtil.md5Hex(properties.getAppSecret() + timeStamp);
        Map<String, Object> body = new HashMap<String, Object>() {{
            put("uid", properties.getAppKey());
            put("serviceType", SERVICE_TYPE);
            put("industryType", INDUSTRY_TYPE);
            put("caller", callReqDTO.getTelephone());
            put("callee", callReqDTO.getCallee());
            put("timestamp", timeStamp);
            put("password", password);
            put("requestId", callReqDTO.getReqNo());
            put("record", 1);
        }};
        log.info("handleCall ----- req body --- {}", JSONUtil.toJsonStr(body));
        HttpRequest httpRequest = HttpUtil.createPost(StrUtil.concat(true, url, CALL_API));
        httpRequest.body(JSONUtil.toJsonStr(body));
        HttpResponse httpResponse = httpRequest.execute();
        CallRespDTO callRespDTO = CallRespDTO.ofError();
        if (httpResponse.isOk()) {
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            log.info("handleCall ----- resp body --- {}", httpResponse.body());
            if (ObjectUtil.equals(jsonObject.get("respCode"),"000000000")) {
                callRespDTO.setSuccess(true);
                callRespDTO.setReqNo(jsonObject.getStr("callId"));
            } else {
                callRespDTO.setMessage(String.format("Channel (%s) %s", properties.getName(), errorMsgMapping(jsonObject.getStr("respMsg"))));
            }
        } else {
            callRespDTO.setMessage(String.format("Channel (%s) %s", properties.getName(), "HTTP请求失败"));
        }

        return callRespDTO;
    }

    @Override
    public AgentRespDTO handleAgent(AgentReqDTO agentReqDTO) {
        return null;
    }

    @Override
    public CallNotifyDTO handleNotify(JSONObject jsonObject) {
        CallNotifyDTO callNotifyDTO = new CallNotifyDTO();
        callNotifyDTO.setReqNo(jsonObject.getStr("callId"));

        Integer serviceResult = jsonObject.getInt("serviceResult");

        // 录音下载地址
        // 获取话单预生成录音地址
        callNotifyDTO.setTempRecordUrl(jsonObject.getStr("recordUrl"));
        if (ObjectUtil.equals(serviceResult, 0)) {
            callNotifyDTO.setResultType(CallResultTypeEnum.SUCCESS.getValue());
            callNotifyDTO.setResultMsg(CallResultTypeEnum.SUCCESS.getMsg());
            // 从接听时间判断
            Integer seconds = DateUtil.timeToSecond(jsonObject.getStr("disconnectTime")) - DateUtil.timeToSecond(jsonObject.getStr("bAnswerTime"));
            callNotifyDTO.setCallSecond(seconds);
            callNotifyDTO.setCallMinute(TimeUtil.secondToMin(seconds));
            // 呼叫时间的计算
            callNotifyDTO.setStartTime(LocalDateTimeUtil.parse(jsonObject.getStr("bAnswerTime"), DatePattern.NORM_DATETIME_FORMATTER));
            callNotifyDTO.setEndTime(LocalDateTimeUtil.parse(jsonObject.getStr("disconnectTime"), DatePattern.NORM_DATETIME_FORMATTER));
        } else {
            callNotifyDTO.setResultType(CallResultTypeEnum.FAIL.getValue());
            callNotifyDTO.setResultMsg(CallResultTypeEnum.FAIL.getMsg());
        }
        return callNotifyDTO;
    }

    @Override
    public boolean createAgent(AgentReqDTO agentReqDTO) {

        // 主叫加白去
        // TODO: 主叫加白需要提供身份证、姓名、中间号， 这三个需要重新搞一下
        return true;

    }


    private String errorMsgMapping(String msg) {
        if (StrUtil.isEmpty(msg)) {
            return "其他错误：" + msg;
        }
        switch (msg) {
            case "authentication fail" : return "鉴权失败";
            case "sla fail" : return "流量限制";
            case "Invalid Input CodeNumber" : return "平台号码错误";
            case "B The interval between the dialed call and the dialed call is too shor" : return "被叫呼叫间隔过短";
            case "The BNumber is in the blacklist" : return "被叫号码命中黑名单";
            case "The ANumber is in the blacklist" : return "主叫号码命中黑名单";
            case "The bNumber daily call restriction" : return "被叫为限呼号码";
            case "The overall ANumber call exceeds the limit" : return "A号呼叫次数超限";
            case "The bNumber monthly call restriction" : return "被叫月呼叫次数超限";
            case "The bNumber or high-risk users are restricted from calling" : return "被叫为高风险号码";
            case "The XNumber call exceeds the limit" : return "X号码呼叫次数超限";
            case "Exceeding The limit" : return "超过限制";
            case "The bNumber is a special dress number" : return "B号为特殊号码";
            case "The ANumber is not in the whitelist or statusAbnormal" : return "号码不在白名单或状态异常";
            case "business number not found" : return "业务号码不存在";
            case "caller number not found" : return "主叫号码不存在";
            case "caller appkey mismatch" : return "越权使用主叫号码";
            case "sponsor appkey mismatch" : return "越权使用业务号码";
            case "callee is black number" : return "被叫为黑名单号码";
            case "click to dial begin error" : return "点击拨号接口异常，请稍后重试";
            case "business number limit" : return "点击拨号业务号码超并发异常";
            case "callid is not found" : return "无效callid";
            case "record download fail" : return "录音下载失败，请稍后重试";
        }
        return "其他错误：" + msg;
    }

    private String errorCodeMapping(String code) {
        switch (code) {
            case "000000000" : return "成功";
            case "100000000" : return "格式非法";
            case "100000001" : return "业务类型不存在";
            case "100000002" : return "参数为空";
            case "100000003" : return "用户不存在";
            case "100000004" : return "用户无效";
            case "100000005" : return "密码不正确";
            case "100000006" : return "时间戳无效";
            case "100000007" : return "钱包不存在";
            case "100000008" : return "余额不足";
            case "100000009" : return "任务无效";
            case "100000010" : return "显号不存在";
            case "100000011" : return "显号无效";
            case "100000012" : return "通道不存在";
            case "100000013" : return "属性不存在";
            case "100000014" : return "模板不存在";
            case "100000015" : return "模板内容无效";
            case "100000016" : return "内容无效";
            case "100000017" : return "铃音不存在";
            case "100000018" : return "铃音内容无效";
            case "100000019" : return "业务类型无效";
            case "100000020" : return "业务请求异常";
            case "100000021" : return "业务响应无效";
            case "100000022" : return "业务响应异常";
            case "100000023" : return "费率不存在";
            case "100000024" : return "计费异常";
            case "100000025" : return "报表类型无效";
            case "100000026" : return "签名不存在";
            case "100000027" : return "导入文件号码为空";
            case "100000028" : return "号码太多";
            case "100000029" : return "网关不存在";
            case "100000030" : return "分机不存在";
            case "100000031" : return "分机用户无效";
            case "100000032" : return "队列不存在";
            case "100000033" : return "呼叫禁止";
            case "100000034" : return "用户忙";
            case "100000035" : return "坐席不存在";
            case "100000036" : return "客户不存在";
            case "100000037" : return "供应商类型无效";
            case "100000038" : return "号码不足";
            case "100000039" : return "按键列表参数无效";
            case "100000040" : return "截止时间限制";
            case "100000041" : return "呼叫不存在";
            case "100000042" : return "IVR 不存在";
            case "100000043" : return "按键不存在";
            case "100000044" : return "按键创建失败";
            case "900000000" : return "异常超时";
            case "900000001" : return "内部异常";
        }
        return "未知";
    }

//    @Override
//    public WhiteRespDTO addWhite(WhiteReqDTO reqDTO) {
////        return WhiteRespDTO.ofSuccess(reqDTO.getNumber());
//        Map<String, Object> body = new HashMap<String, Object>() {{
//            put("accessKey", properties.getAppKey());
//            put("telA", reqDTO.getNumber());
//            put("idCard", reqDTO.getIdNumber());
//            put("telX",reqDTO.getTelX());
//            put("name", reqDTO.getRealName());
//        }};
//        if (StrUtil.isNotEmpty(reqDTO.getCode())) {
//            body.put("code", reqDTO.getCode());
//        }
//        body.put("sign", sign(body));
//        log.info("handleWhite ----- req body --- {}", JSONUtil.toJsonStr(body));
//        HttpRequest httpRequest = HttpUtil.createPost(StrUtil.concat(true, url, WHITE_API));
//        httpRequest.body(JSONUtil.toJsonStr(body));
//        HttpResponse httpResponse = httpRequest.execute();
//
//        if (httpResponse.isOk()) {
//            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
//            log.info("handleWhite ----- resp body --- {}", httpResponse.body());
//            if (ObjectUtil.equals(jsonObject.get("code"),"0000")) {
//                JSONObject data = jsonObject.getJSONObject("data");
//                Integer status = data.getInt("status");
//                if (status == 0) {
//                    return WhiteRespDTO.ofWaiting(reqDTO.getNumber());
//                } else if (status == 1) {
//                    return WhiteRespDTO.ofSuccess(reqDTO.getNumber());
//                } else if (status == 2) {
//                    return WhiteRespDTO.ofFail(reqDTO.getNumber(), jsonObject.getStr("message"));
//                }
//            } else {
//                return WhiteRespDTO.ofFail(reqDTO.getNumber(), jsonObject.getStr("message"));
//            }
//        } else {
//            return WhiteRespDTO.ofFail(reqDTO.getNumber(), "API请求失败");
//        }
//        return WhiteRespDTO.ofDefault(reqDTO.getNumber());
//    }

    @Override
    public JSONObject getAccountInfo(String agent) {
        return null;
    }
}
